cmake_minimum_required(VERSION 3.20)
project(ps2_native_gs LANGUAGES C CXX)
if(APPLE)
    enable_language(OBJCXX)
endif()
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# PS2_NATIVE_GS_VULKAN: build the Vulkan backend (always on Windows; on macOS an extra module through MoltenVK,
# used to validate the Vulkan backend against the Metal one with gs-replay).
option(PS2_NATIVE_GS_VULKAN "Build the Vulkan backend" ON)

set(CORE_SOURCES src/native_gs_module.mm src/ps2_gs_memory.cpp)
set(CORE_INCLUDES include src)

if(PS2_NATIVE_GS_VULKAN OR NOT APPLE)
    include(FetchContent)
    FetchContent_Declare(vulkan_headers GIT_REPOSITORY https://github.com/KhronosGroup/Vulkan-Headers.git GIT_TAG v1.4.309 GIT_SHALLOW TRUE)
    FetchContent_Declare(volk GIT_REPOSITORY https://github.com/zeux/volk.git GIT_TAG 1.4.304 GIT_SHALLOW TRUE)
    FetchContent_GetProperties(vulkan_headers)
    if(NOT vulkan_headers_POPULATED)
        FetchContent_Populate(vulkan_headers)
    endif()
    FetchContent_GetProperties(volk)
    if(NOT volk_POPULATED)
        FetchContent_Populate(volk)
    endif()
    function(add_vulkan_module target kind)
        add_library(${target} ${kind} ${CORE_SOURCES} src/gpu_vulkan.cpp "${volk_SOURCE_DIR}/volk.c")
        target_include_directories(${target} PRIVATE ${CORE_INCLUDES} "${volk_SOURCE_DIR}" "${vulkan_headers_SOURCE_DIR}/include")
        target_compile_definitions(${target} PRIVATE GS_BACKEND_VULKAN)
        set_property(TARGET ${target} PROPERTY CXX_STANDARD 20)
        set_target_properties(${target} PROPERTIES PREFIX "lib")
        if(WIN32)
            target_compile_definitions(${target} PRIVATE VK_USE_PLATFORM_WIN32_KHR)
            set_source_files_properties("${volk_SOURCE_DIR}/volk.c" PROPERTIES COMPILE_DEFINITIONS VK_USE_PLATFORM_WIN32_KHR)
        endif()
    endfunction()
endif()

if(APPLE)
    # macOS: Metal backend.
    add_library(ps2-native-gs MODULE ${CORE_SOURCES} src/gpu_metal.mm)
    target_include_directories(ps2-native-gs PRIVATE ${CORE_INCLUDES})
    target_compile_options(ps2-native-gs PRIVATE $<$<COMPILE_LANGUAGE:OBJCXX>:-fobjc-arc> -march=armv8-a+crc)
    set_property(TARGET ps2-native-gs PROPERTY CXX_STANDARD 20)
    set_property(TARGET ps2-native-gs PROPERTY OBJCXX_STANDARD 20)
    set_target_properties(ps2-native-gs PROPERTIES PREFIX "lib" SUFFIX ".so")
    target_link_libraries(ps2-native-gs PRIVATE "-framework Metal" "-framework Cocoa" "-framework QuartzCore" "-framework ImageIO" "-framework CoreGraphics")
    if(PS2_NATIVE_GS_VULKAN)
        add_vulkan_module(ps2-native-gs-vk MODULE)
        set_property(TARGET ps2-native-gs-vk PROPERTY OBJCXX_STANDARD 20)
        target_compile_options(ps2-native-gs-vk PRIVATE $<$<COMPILE_LANGUAGE:OBJCXX>:-fobjc-arc> -march=armv8-a+crc)
        set_target_properties(ps2-native-gs-vk PROPERTIES SUFFIX ".so")
        target_link_libraries(ps2-native-gs-vk PRIVATE "-framework CoreFoundation" "-framework CoreGraphics" "-framework ImageIO")
    endif()
else()
    # Windows (and other platforms): Vulkan backend. The .mm file is plain C++ outside macOS.
    set_source_files_properties(src/native_gs_module.mm PROPERTIES LANGUAGE CXX COMPILE_OPTIONS "-xc++")
    add_vulkan_module(ps2-native-gs SHARED)
endif()

# Replays a GS dump through a renderer module and compares frames between two modules.
add_executable(gs-replay tools/gs_replay.cpp)
target_include_directories(gs-replay PRIVATE include)
set_property(TARGET gs-replay PROPERTY CXX_STANDARD 20)
if(WIN32)
else()
    target_link_libraries(gs-replay PRIVATE ${CMAKE_DL_LIBS})
endif()
